#include <iostream>
#include <string.h>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
using boost::asio::ip::tcp;

struct DataHead
{
	unsigned char protocol;
	unsigned char version;
	unsigned char game;
	unsigned char server_type;
	unsigned int length;
	unsigned int player_id;
	unsigned short server;
	unsigned short next_head;
};

struct GameHead
{
	unsigned int character_id;
	unsigned short length;
	unsigned short format;
};

char buf[10240];
int buf_len = sizeof(struct DataHead) + sizeof(struct GameHead) + 9000;

class client
{
public:
	client(boost::asio::io_service& io_service,tcp::endpoint& endpoint)
		: socket(io_service)
	{
		socket.async_connect(endpoint,
			boost::bind(&client::handle_connect,this,boost::asio::placeholders::error)
		);
	}

	~client()
	{
	}

private:
	void handle_connect(const boost::system::error_code& error)
	{
		if(!error)
		{
			boost::asio::async_write(socket,boost::asio::buffer(buf, buf_len),
				boost::bind(&client::handle_write_done,this,boost::asio::placeholders::error));

		}		
		else
		{
			socket.close();
		}
	}

	void handle_write_done(const boost::system::error_code& error)
	{
		if(error)
		{
			std::cout << "write call failed" << std::endl;

			return;
		}

		socket.async_read_some(boost::asio::buffer(buf,9000),
			boost::bind(&client::handle_read_done, 
			this, 
			boost::asio::placeholders::error, 
			boost::asio::placeholders::bytes_transferred)
			);
	}

	void handle_read_done(const boost::system::error_code& error, size_t bytes_transferred)
	{
		if(!error)
		{
			std::cout << "recive data length: " << bytes_transferred << std::endl;

			std::cout << buf + sizeof(struct DataHead) + sizeof(struct GameHead) << std::endl;

			
			msg_str = "";
			std::cout << "input message: ";
			std::cin >> msg_str;
		
			memset(buf,'\0', 9000);

			struct DataHead *pHead = (struct DataHead *)buf;
			pHead->protocol = 1;
			pHead->version = 1;
			pHead->server_type = 1;
			pHead->player_id = 1;
			pHead->server = 1;
			pHead->next_head = 0;

			struct GameHead *pGameHead = (struct GameHead *)(buf + sizeof(struct DataHead));

			pGameHead->character_id = 1;
			pGameHead->length = (msg_str.length() + 3) / 4;
			pGameHead->format = 1;

			strcpy(buf + sizeof(struct DataHead) + sizeof(struct GameHead), msg_str.c_str());
			boost::asio::async_write(socket,boost::asio::buffer(buf),
				boost::bind(&client::handle_write_done,this,boost::asio::placeholders::error));

		}	
		else
		{
			std::cout << "read call failed" << std::endl;
			socket.close();
		}
	}

	void handle_write(const boost::system::error_code& error)
	{
		msg_str = "";
		std::cout << "input message: ";
		std::cin >> msg_str;
		
		memset(buf,'\0', 9000);

		struct DataHead *pHead = (struct DataHead *)buf;
		pHead->protocol = 1;
		pHead->version = 1;
		pHead->server_type = 1;
		pHead->player_id = 1;
		pHead->server = 1;
		pHead->next_head = 0;

		struct GameHead *pGameHead = (struct GameHead *)(buf + sizeof(struct DataHead));

		pGameHead->character_id = 1;
		pGameHead->length = (msg_str.length() + 3) / 4;
		pGameHead->format = 1;

		strcpy(buf + sizeof(struct DataHead) + sizeof(struct GameHead), msg_str.c_str());
		boost::asio::async_write(socket,boost::asio::buffer(buf),
			boost::bind(&client::handle_write,this,boost::asio::placeholders::error));
	}

private:
	std::string msg_str;
	tcp::socket socket;
};


std::string firstPacket = "{\"evt\":1,\"characterId\":1}";

int main(int argc,char* argv[])
{
	memset(buf,'\0', 10240);

	struct DataHead *pHead = (struct DataHead *)buf;
	pHead->protocol = 1;
	pHead->version = 1;
	pHead->server_type = 1;
	pHead->player_id = 1;
	pHead->server = 1;
	pHead->next_head = 0;

	struct GameHead *pGameHead = (struct GameHead *)(buf + sizeof(struct DataHead));

	pGameHead->character_id = 1;
	pGameHead->length = (firstPacket.length() + 3) / 4;
	pGameHead->format = 1;

	strcpy(buf + sizeof(struct DataHead) + sizeof(struct GameHead), firstPacket.c_str());

	boost::asio::io_service io_service;

	tcp::endpoint endpoint(boost::asio::ip::address_v4::from_string("127.0.0.1"/*argv[1]*/),7000/*argv[2]*/);

	boost::shared_ptr<client> client_ptr(new client(io_service,endpoint));

	io_service.run();
	
	return 0;
}
